package com.lanyou.esb.cook.proxy.common;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.commons.lang3.StringUtils;

import redis.clients.jedis.Jedis;

import com.lanyou.esb.cook.proxy.dao.impl.ParamSetDao;
import com.lanyou.esb.cook.proxy.entity.ParamSet;
import com.lanyou.esb.cook.proxy.exception.ParamSetRuntimeException;
import com.lanyou.esb.cook.proxy.meta.AuthType;
import com.lanyou.esb.cook.proxy.redis.JedisPoolUtils;

/**
 * 参数工厂
 * 
 * @author Davey.wu
 */
public final class ParamFactory {

	/** 配置参数列表 **/
	public static final Map<String, String> PARAM_NEED = new HashMap<>();
	/** 参数配置映射表 **/
	private static final Map<String, ParamSet> MAP_PARAM_SET = new HashMap<>();

	/** HTTP_BASIC_KEY 认证所需参数，Key:字段名称;value: 是否必须 **/
	private static final Map<String, Boolean> PARAMETER_HTTP_BASIC_KEY = new HashMap<>();
	/** OAUTH 认证所需参数 **/
	private static final Map<String, Boolean> PARAMETER_OAUTH = new HashMap<>();
	/** WS_SECURITY 认证所需参数 ，Key:字段名称;value: 是否必须 **/
	private static final Map<String, Boolean> PARAMETER_WS = new HashMap<>();
	/** NOAUTH 认证所需参数，Key:字段名称;value: 是否必须 **/
	private static final Map<String, Boolean> PARAMETER_NOAUTH = new HashMap<>();
	static {
		PARAM_NEED.put(Constants.REDIS_SERVER, Constants.REDIS_SERVER);
		PARAM_NEED
				.put(Constants.ACCESSTOKEN_EXPIRES_IN, Constants.INTEGER_TYPE);
		PARAM_NEED.put(Constants.ACCESSTOKEN_DAY_APP_UPPER_LIMIT,
				Constants.INTEGER_TYPE);

		/** OAUTH认证类型应该包含调用方系统编码 **/
		PARAMETER_NOAUTH.put(Constants.CALL_SYSTEM_CODE, true);

		/** 基本认证类型应该包含密钥，调用方系统编码 **/
		PARAMETER_HTTP_BASIC_KEY.put(Constants.APPLY_KEY, true);
		PARAMETER_HTTP_BASIC_KEY.put(Constants.CALL_SYSTEM_CODE, true);

		/** OAUTH认证类型应该包含密钥，调用方系统编码 **/
		PARAMETER_OAUTH.put(Constants.ACCESS_TOKEN, true);
		PARAMETER_OAUTH.put(Constants.CALL_SYSTEM_CODE, true);

		/** OAUTH认证类型应该包含密钥，调用方系统编码 **/
		PARAMETER_WS.put(Constants.APPLY_KEY, true);
		PARAMETER_WS.put(Constants.CALL_SYSTEM_CODE, true);

	}

	public static Map<String, Boolean> getParameter4HttpBasickey() {
		return PARAMETER_HTTP_BASIC_KEY;
	}

	public static Map<String, Boolean> getParameter4Oauth() {
		return PARAMETER_OAUTH;
	}

	public static Map<String, Boolean> getParameter4WsSecurity() {
		return PARAMETER_WS;
	}

	public static Map<String, Boolean> getParameter4NoAuth() {
		return PARAMETER_NOAUTH;
	}

	public static Map<String, Boolean> getParameters(AuthType authType) {
		switch (authType) {
		case HTTP_BASIC_KEY:
			return getParameter4HttpBasickey();
		case WS_SECURITY:
			return getParameter4WsSecurity();
		case OAUTH:
			return getParameter4Oauth();
		case NOAUTH:
			return getParameter4NoAuth();
		default:
			return null;
		}
	}

	/**
	 * 更新配置参数
	 * 
	 * @param dao
	 */
	public synchronized static void update(ParamSetDao dao) {
		boolean needUpdate = false;
		try {
			if (MAP_PARAM_SET.size() == 0) {
				needUpdate = true;
			}
			// 检查必要的参数是否存在
			if (!needUpdate) {
				ParamFactory.checkNeedParamSet();
			}
		} catch (Exception e) {
			// 有些参数不存在，则需要更新
			needUpdate = true;
		}
		if (!needUpdate) {
			return;
		}
		// 清空
		MAP_PARAM_SET.clear();
		JedisPoolUtils.destroy();
		// 加载参数配置
		List<ParamSet> list = null;
		//数据库加载可能有延迟
		int times=3;
		do{
			times--;
			try{
				list = dao.findAll();
				if(list!=null&&!list.isEmpty()){
					times=0;
				}
			}catch(Exception e){
				try {
					Thread.currentThread().sleep(3000);
				} catch (InterruptedException e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				}
			}
		}while(times>0);
		if (list == null || list.size() == 0) {
			return;
		}
		for (ParamSet paramSet : list) {
			if (StringUtils.isBlank(paramSet.getName())) {
				continue;
			}
			MAP_PARAM_SET.put(paramSet.getName(), paramSet);
		}
		// 检查必须的参数配置
		ParamFactory.checkNeedParamSet();
	}

	public static ParamSet getParamSet(String name) {
		if (MAP_PARAM_SET.size() == 0) {
			return null;
		}
		return MAP_PARAM_SET.get(name);
	}

	/**
	 * 检查必须的参数是否存在
	 * 
	 * @throws ParamSetException
	 * 
	 * @throws ParamSetRuntimeException
	 */
	public static void checkNeedParamSet() {

		for (Entry<String, String> entry : PARAM_NEED.entrySet()) {
			if (Constants.INTEGER_TYPE.equals(entry.getValue())) {
				getInt(entry.getKey());
				continue;
			}
			if (Constants.STRING_TYPE.equals(entry.getValue())) {
				String name = entry.getKey();
				String value = getString(name);
				System.out.println("name=" + name + ",value=" + value);
				continue;
			}
		}
		// 验证是否能连接REDIS服务器
		Jedis jedis = null;
		boolean broken = false;
		try {
			jedis = JedisPoolUtils.getJedis();
		} catch (Exception e) {
			broken = true;
			System.out.println("ERROR:无法连接到redis服务器【"
					+ getString(Constants.REDIS_SERVER)
					+ "】，请查看redis服务参数设置是否正确，详细信息：" + e.getMessage());
			throw e;
		} finally {
			if (jedis != null) {
				JedisPoolUtils.returnRes(jedis, broken);
			}
		}
	}

	/**
	 * 判断是否存在参数
	 * 
	 * @return
	 */
	public static boolean haveParam() {
		if (MAP_PARAM_SET.size() == 0) {
			return false;
		}
		return true;
	}

	/**
	 * 获取整型参数
	 * 
	 * @param name
	 * @return
	 * @throws ParamSetRuntimeException
	 */
	public static int getInt(String name) throws ParamSetRuntimeException {
		ParamSet param = ParamFactory.getParamSet(name);
		if (param == null) {
			String msg = "ERROR:参数【" + name + "】不存在";
			System.out.println(msg);
			throw new ParamSetRuntimeException(msg, "");
		}
		if (StringUtils.isBlank(param.getValue())) {
			String msg = "ERROR:参数【" + name + "】值为空";
			System.out.println(msg);
			throw new ParamSetRuntimeException(msg, "");
		}
		int result = 0;
		try {
			result = Integer.parseInt(param.getValue());
		} catch (Exception e) {
			String msg = "ERROR:参数【" + name + "】应该为正整数";
			System.out.println(msg);
			throw new ParamSetRuntimeException(msg, "");
		}
		if (result == 0) {
			String msg = "ERROR:参数【" + name + "】应该为正整数";
			System.out.println(msg);
			throw new ParamSetRuntimeException(msg, "");
		}
		return result;
	}

	/**
	 * 获取字符串型参数
	 * 
	 * @param name
	 * @return
	 * @throws ParamSetRuntimeException
	 */
	public static String getString(String name) throws ParamSetRuntimeException {
		ParamSet param = ParamFactory.getParamSet(name);
		if (param == null) {
			String msg = "ERROR:参数【" + name + "】不存在";
			System.out.println(msg);
			throw new ParamSetRuntimeException(msg, "");
		}
		if (StringUtils.isBlank(param.getValue())) {
			String msg = "ERROR:参数【" + name + "】值为空";
			System.out.println(msg);
			throw new ParamSetRuntimeException(msg, "");
		}
		return param.getValue();
	}

	public static void clear() {
		if (MAP_PARAM_SET == null) {
			return;
		}
		MAP_PARAM_SET.clear();
	}
}
